/* Copyright 2024，Topsec Network Technology Inc.
* ALL rights reserved.
*
* This file is part of the openHiTLS project.
*
* openHiTLS is licensed under the Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
*
*     http://license.coscl.org.cn/MulanPSL2
*
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/

#include <sys/times.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <stdio.h> 
#include <stdlib.h> 
#include <stdint.h> 
#include <string.h>
#include "crypt_eal_cipher.h" // 对称加解密接口头文件 
#include "bsl_sal.h"
#include "bsl_err.h"
#include "crypt_algid.h" // 算法id列表 
#include "crypt_errno.h" // 错误码列表 
#include <stdio.h>
#include <sys/timeb.h>
#include <signal.h>
#include <time.h>
#include <unistd.h>
#include "crypt_eal_md.h"
#include "crypt_eal_rand.h" // 随机数头文件
#include "crypt_eal_pkey.h" // 签名验签头文件

////////////////////
//运行标志位
static volatile int run = 0;

//对称加密算法测试的包大小
static int lengths_list[] = {
    16, 64, 256, 1024, 8 * 1024, 16 * 1024
};
static int lengthsMax = 16 * 1024;
static int SIZE_NUM    =     6;
#define MAX_BLOCK_SIZE 128

///////////////////////////////////////
//非对称算法密钥对位数
static int lengths_list_asy[] = {
    512, 1024, 2048, 3072, 4096, 7680,15360
};
static int SIZE_NUM_ASY    =     5;

//////////////测试的时间（秒）
static int  TEST_TIME = 3;
# define TM_START        0
# define TM_STOP         1

static unsigned char iv[2 * MAX_BLOCK_SIZE / 8];

typedef enum {
	CRYPT_TYPE,
	MAC_TYPE,
	ASY_TYPE
} ALG_TYPE;

struct alg_test{
	char * name;/////////////算法名称
	CRYPT_CIPHER_AlgId alg;//算法ID
	ALG_TYPE type;///////////算法类型
	int keylen; /////////////秘钥长度
	char * buf;//////////////测试用的数据指针
	int istest;//////////////是否需要测试
};

struct alg_test algs_name[]={
	{"MD5",BSL_CID_MD5,MAC_TYPE,16,0},
	{"SHA1",BSL_CID_SHA1,MAC_TYPE,16,0},
	{"SHA224",BSL_CID_SHA224,MAC_TYPE,16,0},
	{"SHA256",BSL_CID_SHA256,MAC_TYPE,16,0},
	{"SHA384",BSL_CID_SHA384,MAC_TYPE,16,0},
	{"SHA512",BSL_CID_SHA512,MAC_TYPE,16,0},
	{"SHA3_224",BSL_CID_SHA3_224,MAC_TYPE,16,0},
	{"SHA3_256",BSL_CID_SHA3_256,MAC_TYPE,16,0},
	{"SHA3_384",BSL_CID_SHA3_384,MAC_TYPE,16,0},
	{"SHA3_512",BSL_CID_SHA3_512,MAC_TYPE,16,0},
	{"SHAKE128",BSL_CID_SHAKE128,MAC_TYPE,16,0},
	{"SHAKE256",BSL_CID_SHAKE256,MAC_TYPE,16,0},
	{"SM3",BSL_CID_SM3,MAC_TYPE,16,0},
	{"AES128_CBC",BSL_CID_AES128_CBC,CRYPT_TYPE,16,0},
	{"AES192_CBC",BSL_CID_AES192_CBC,CRYPT_TYPE,24,0},
	{"AES256_CBC",BSL_CID_AES256_CBC,CRYPT_TYPE,32,0},
	{"AES128_GCM",BSL_CID_AES128_GCM,CRYPT_TYPE,16,0},
	{"AES192_GCM",BSL_CID_AES192_GCM,CRYPT_TYPE,24,0},
	{"AES256_GCM",BSL_CID_AES256_GCM,CRYPT_TYPE,32,0},
	{"SM4_CBC",BSL_CID_SM4_CBC,CRYPT_TYPE,16,0},
	{"SM4_GCM",BSL_CID_SM4_GCM,CRYPT_TYPE,16,0},
	{"RSA",BSL_CID_RSA,ASY_TYPE,16,0},
	{"SM2",BSL_CID_SM2,ASY_TYPE,16,0}
};

static double results[100][100];
static double asyresults[100][100][8];

static void speed_alarmed(int sig)
{
    signal(SIGALRM, speed_alarmed);
    run = 0;
}

double speed_time(int stop)
{
    double ret = 0;
    struct tms rus;
    clock_t now;
	
    static clock_t tmstart;
	times(&rus);
    now = rus.tms_utime;

    if (stop == TM_START) {
        tmstart = now;
    } else {
        long int tck = sysconf(_SC_CLK_TCK);
        ret = (now - tmstart) / (double)tck;
    }

    return ret;
}

void PrintLastError(void) 
{ 
    const char *file = NULL; 
    uint32_t line = 0; 
    BSL_ERR_GetLastErrorFileLine(&file, &line); // 获取错误发生的文件名和行数 
    printf("failed at file %s at line %d\n", file, line); 
} 

///////////////////
//测试的时长
static double Speed_Time_Test(int s)
{
    double ret = speed_time(s);
    if (s == TM_STOP)
        alarm(0);
    return ret;
}

static void cipher_message(const char *s, int length, int tm)
{
    printf("Doing %s ops for %ds on %d size blocks: ", s, tm, length);
    run = 1;
    alarm(tm);
}

static void asy_print_message(const char *str, const char *str2, unsigned int bits,
                               int tm)
{
    printf("Doing %u bits %s %s ops for %ds: ", bits, str, str2, tm);
    run = 1;
    alarm(tm);
}

static void print_result(int index, int run_no, int count, double time_used)
{
    if (count == -1) {
        printf("%s error!\n", algs_name[index].name);
        return;
    }
    printf("%d %s ops in %.2fs\n", count, algs_name[index].name, time_used);
    results[index][run_no] = ((double)count) / time_used * lengths_list[run_no];
}

int Speed_Cipher(CRYPT_EAL_CipherCtx *ctx, unsigned char *out,
               unsigned char *in, unsigned int inl)
{
	uint32_t len = inl;
	int ret = CRYPT_EAL_CipherUpdate(ctx, (const uint8_t *)in, (uint32_t)inl, in+inl, &len);
	if(ret != CRYPT_SUCCESS){
		PrintLastError();
		exit(-1);
	}
	return 1;
}

static int Cipher_loop(CRYPT_EAL_CipherCtx * ctx,unsigned char * buf,int len)
{
    int count;

    if (ctx == NULL){
        printf("ctx:%p\n",ctx);
		return -1;
	}
    for (count = 0; run && count < 0xfffffff; count++)
        if (Speed_Cipher(ctx, buf, buf, (size_t)len) <= 0){
            return -1;
		}
    return count;
}

int Speed_MD(CRYPT_EAL_MdCTX *ctx, unsigned char *out,
               unsigned char *in, unsigned int inl)
{
	int ret = CRYPT_EAL_MdInit(ctx);

	if(ret != CRYPT_SUCCESS){
		PrintLastError();
		exit(-1);
	}
	ret= CRYPT_EAL_MdUpdate(ctx, in, inl);
	if(ret != CRYPT_SUCCESS){
		PrintLastError();
		exit(-1);
	}
	int md_len=64;
	ret = CRYPT_EAL_MdFinal(ctx, out, &md_len);
	if(ret != CRYPT_SUCCESS){
		PrintLastError();
		exit(-1);
	}
	CRYPT_EAL_MdDeinit(ctx);
	return 1;
}

static int MD_loop(CRYPT_EAL_MdCTX * ctx,unsigned char * buf,int len)
{
    int count;

    if (ctx == NULL){
        printf("ctx:%p\n",ctx);
		return -1;
	}
    for (count = 0; run && count < 0xfffffff; count++)
        if (Speed_MD(ctx, buf, buf, (size_t)len) <= 0){
            return -1;
		}
    return count;
}

static int Gen_loop(CRYPT_EAL_PkeyCtx * ctx,unsigned char * buf,int len)
{
    int count;

    if (ctx == NULL){
        printf("ctx:%p\n",ctx);
		return -1;
	}
    for (count = 0; run && count < 0xfffffff; count++){
        // 生成密钥对
		int ret = CRYPT_EAL_PkeyGen(ctx);
		if (ret != CRYPT_SUCCESS) {
			printf("error code is %x\n", ret);
			PrintLastError();
			exit(-1);
		}
	}
    return count;
}

static int Sign_loop_data(CRYPT_EAL_PkeyCtx * ctx,unsigned char * buf,int len)
{
    int count;

    if (ctx == NULL){
        printf("ctx:%p\n",ctx);
		return -1;
	}
    for (count = 0; run && count < 0xfffffff; count++){
        // 签名不计算hash
		uint32_t signLen = 1024;
		int ret = CRYPT_EAL_PkeySignData(ctx, buf, 32, buf+32, &signLen); 
		if (ret != CRYPT_SUCCESS) { 
			printf("error code is %x\n", ret); 
			PrintLastError(); 
			exit(-1);
		} 
	}
    return count;
}

static int Verify_loop_data(CRYPT_EAL_PkeyCtx * ctx,unsigned char * buf,int len)
{
    int count;

    if (ctx == NULL){
        printf("ctx:%p\n",ctx);
		return -1;
	}
    for (count = 0; run && count < 0xfffffff; count++){
        // 签名不计算hash
		uint32_t signLen = (len*8 + 7) >> 3;
		int ret = CRYPT_EAL_PkeyVerifyData(ctx, buf, 32, buf+32, signLen); 
		if (ret != CRYPT_SUCCESS) { 
			printf("error code is %x\n", ret); 
			PrintLastError(); 
			exit(-1);
		} 
	}
    return count;
}

static int Sign_loop(CRYPT_EAL_PkeyCtx * ctx,unsigned char * buf,int len,CRYPT_MD_AlgId id,int * signOutLen)
{
    int count;
	uint32_t signLen = 1024;
    if (ctx == NULL){
        printf("ctx:%p\n",ctx);
		return -1;
	}
    for (count = 0; run && count < 0xfffffff; count++){
        //签名不计算hash
		signLen = 1024;
		int ret = CRYPT_EAL_PkeySign(ctx,id, buf, 512, buf+512, &signLen); 
		if (ret != CRYPT_SUCCESS) { 
			printf("error code is %x\n", ret); 
			PrintLastError(); 
			exit(-1);
		} 
	}
	*signOutLen = (int)signLen;
    return count;
}

static int Verify_loop(CRYPT_EAL_PkeyCtx * ctx,unsigned char * buf,int len,CRYPT_MD_AlgId id,int signOutLen)
{
    int count;

    if (ctx == NULL){
        printf("ctx:%p\n",ctx);
		return -1;
	}
    for (count = 0; run && count < 0xfffffff; count++){
        // 签名不计算hash
		uint32_t signLen = 32;
		int ret = CRYPT_EAL_PkeyVerify(ctx, id,buf, 512, buf+512, signOutLen); 
		if (ret != CRYPT_SUCCESS) { 
			printf("error code is %x\n", ret); 
			PrintLastError(); 
			exit(-1);
		} 
	}
    return count;
}


static int Encrypt_loop(CRYPT_EAL_PkeyCtx * ctx,unsigned char * buf,int len,int * signOutLen)
{
    int count;
	uint32_t signLen = 1024;
    if (ctx == NULL){
        printf("ctx:%p\n",ctx);
		return -1;
	}
    for (count = 0; run && count < 0xfffffff; count++){
		signLen = 1024;
		int ret = CRYPT_EAL_PkeyEncrypt(ctx, buf, 32, buf+32, &signLen); 
		if (ret != CRYPT_SUCCESS) { 
			printf("error code is %x\n", ret); 
			PrintLastError(); 
			exit(-1);
		} 
	}
	*signOutLen = (int)signLen;
    return count;
}

static int Decrypt_loop(CRYPT_EAL_PkeyCtx * ctx,unsigned char * buf,int len,int signOutLen)
{
    int count;
	uint32_t signLen = 1024;
    if (ctx == NULL){
        printf("ctx:%p\n",ctx);
		return -1;
	}
    for (count = 0; run && count < 0xfffffff; count++){
		signLen = 1024;
		int ret = CRYPT_EAL_PkeyDecrypt(ctx, buf+32, signOutLen, buf+32+signOutLen, &signLen); 
		if (ret != CRYPT_SUCCESS) { 
			printf("error code is %x\n", ret); 
			PrintLastError(); 
			exit(-1);
		} 
	}

    return count;
}

void print_crypt_header(){
	 printf("加解密算法结果如下:\n");
     printf("type        ");
	 
	for (int testnum = 0; testnum < SIZE_NUM; testnum++)
            printf("%7d bytes", lengths_list[testnum]);
    printf("\n");
}

void print_help(){
	printf("参数:\n");
	printf(" -help				输出帮助信息\n");
	printf(" -s					运行性能测试的时间(1-9999)\n");
	printf(" -b					运行性能测试的自定义包大小\n");
	printf("支持的算法:\n");
	for(int i=0;i<sizeof(algs_name)/sizeof(struct alg_test);i++){
		if((i != 0) && (i % 4 == 0)){
			printf("\n");
		}
		printf("%20s",(const char *)algs_name[i].name);
	}
	printf("\n");
}

void SetRsaPubKey(CRYPT_EAL_PkeyPub *pubKey, uint8_t *n, uint32_t nLen, uint8_t *e, uint32_t eLen);
void SetRsaPara(CRYPT_EAL_PkeyPara *para, uint8_t *e, uint32_t eLen, uint32_t bits);

int main(int argc, char *argv[]){
	////////////////
	//参数获取 
	int opt;
	while ((opt = getopt(argc, argv, "s:b:")) != -1) {  
        switch (opt) {  
        case 's':  
			TEST_TIME = atoi(optarg);
            if(TEST_TIME <= 0 || TEST_TIME > 9999){
				fprintf(stderr,"测试时间需要再0秒到9999秒之间");
				exit(EXIT_FAILURE);  
			}				
            break;  
        case 'b':  
            SIZE_NUM = atoi(optarg);
            if(SIZE_NUM < 16 || SIZE_NUM > 1024*16){
				fprintf(stderr,"测试自定义包长度需要再16字节到1024*16字节之间.");
				exit(EXIT_FAILURE);  
			}
			lengths_list[0] = SIZE_NUM;
			SIZE_NUM = 1;
            break;  
        default: /* '?' */  
            print_help();
            exit(EXIT_FAILURE);  
        }  
    }  
  
	int algslen = sizeof(algs_name)/sizeof(struct alg_test);
  
    /* optind 现在是第一个非选项参数的索引 */  
    if (optind < argc) {  
        //有参数 则需要将需要测试的算法全部给0
		for(int i=0;i<algslen;i++){
			algs_name[i].istest = 0;
		}		

        while (optind < argc) {
			int isfind = 0;
			for(int i=0;i<algslen;i++){
				if(strcmp(algs_name[i].name,argv[optind]) == 0){
					/////
					//找到想测试的算法
					algs_name[i].istest = 1;
					isfind = 1;
					break;
				}
			}
			if(isfind == 0){
				//////////////////////
				//没找到算法  则返回错误
				fprintf(stderr,"speed: 未知算法%s\n",argv[optind]);
				print_help();
				exit(EXIT_FAILURE);  
			}
			optind++;
		}			  
    } else {  
        /* 没有非选项参数 */  
		for(int i=0;i<algslen;i++){
			algs_name[i].istest = 1;
		}
    }
	
	
	CRYPT_EAL_CipherCtx * ctx=NULL;
	static unsigned char keycipher[1024];
	long count = 0;
	double d = 0.0;
	CRYPT_MD_AlgId mdId = CRYPT_MD_SHA256;
	uint8_t userId[32] = { 0 }; 
	int signLen;
	//////////////////////
	//RSA 算法用到的特殊变量
	uint8_t e[] = {1, 0, 1};
	CRYPT_EAL_PkeyPara para = {0};
	CRYPT_EAL_PkeyPub pubKey = {0};
	uint8_t pubE[600];
	uint8_t pubN[600];

	CRYPT_RSA_PkcsV15Para pkcsv15 = {mdId};
	int32_t noPad = CRYPT_PKEY_RSA_NO_PAD;
	int breaksig = 0;
	/////////
	//注册信号
	signal(SIGALRM, speed_alarmed);
	
	static BSL_SAL_MemCallback cb = {malloc, free};
    BSL_SAL_RegMemCallback(&cb);
	// 初始化全局随机数, 使用linux的/dev/random默认熵源
    int ret = CRYPT_EAL_RandInit(CRYPT_RAND_SHA256, NULL, NULL, NULL, 0);
    if (ret != CRYPT_SUCCESS) {
        printf("CRYPT_EAL_RandInit: error code is %x\n", ret);
        PrintLastError();
        exit(EXIT_FAILURE);  
    }
	///////////////////////
	//申请测试用的buff，同时使用随机数赋值
	for(int i=0;i<algslen;i++){
		//重播种
		ret = CRYPT_EAL_RandSeed(); 
		if (ret != CRYPT_SUCCESS) { 
			printf("CRYPT_EAL_RandSeed: error code is %x\n", ret);
			PrintLastError();
			exit(EXIT_FAILURE);  
		} 
		algs_name[i].buf = malloc(lengthsMax*3);
		// 获得len长度的随机数序列 
		ret = CRYPT_EAL_Randbytes(algs_name[i].buf, lengthsMax*3); 
		if (ret != CRYPT_SUCCESS) { 
			printf("CRYPT_EAL_Randbytes: error code is %x\n", ret);
			PrintLastError();
			exit(EXIT_FAILURE);   
		}
	}
	
	////////////////////
	//对称加密的key 随机赋值
	ret = CRYPT_EAL_RandSeed(); 
	if (ret != CRYPT_SUCCESS) { 
		printf("CRYPT_EAL_RandSeed: error code is %x\n", ret);
		PrintLastError();
		exit(EXIT_FAILURE);  
	}
	ret = CRYPT_EAL_Randbytes(keycipher, 1024); 
	if (ret != CRYPT_SUCCESS) { 
		printf("CRYPT_EAL_Randbytes: error code is %x\n", ret);
		PrintLastError();
		exit(EXIT_FAILURE);   
	}
		
	for(int i=0;i<algslen;i++){
		if(algs_name[i].istest == 0){
			continue;
		}
		//////////////////
		//如果是加解密类型的
		if(algs_name[i].type == CRYPT_TYPE){
			////////////////////////////
			//开始实际执行
			for(int testnum=0;testnum<SIZE_NUM;testnum++){
				//////////////////////
				//初始化套件
				ctx = CRYPT_EAL_CipherNewCtx(algs_name[i].alg);
				if(ctx == NULL){
					printf("error CRYPT_EAL_CipherNewCtx\n");
					exit(-1);
				}
				int ret = CRYPT_EAL_CipherInit(ctx, keycipher, algs_name[i].keylen, iv, 16, true);
				if(ret != CRYPT_SUCCESS){
					printf("error CRYPT_EAL_CipherInit %08X\n",ret);
					PrintLastError();
					exit(-1);
				}
				ret = CRYPT_EAL_CipherSetPadding(ctx, 0);				
				
				cipher_message(algs_name[i].name,lengths_list[testnum],TEST_TIME);
				Speed_Time_Test(TM_START);
				
				count = Cipher_loop(ctx,algs_name[i].buf,lengths_list[testnum]);
				d = Speed_Time_Test(TM_STOP);
                print_result(i, testnum, count, d);

				/////释放
				CRYPT_EAL_CipherFreeCtx(ctx);
			}
		}
		if(algs_name[i].type == MAC_TYPE){
			//////////////////////
			//初始化套件
			CRYPT_EAL_MdCTX * ctx;
			ctx = CRYPT_EAL_MdNewCtx(algs_name[i].alg);
			if(ctx == NULL){
				printf("error CRYPT_EAL_MdNewCtx\n");
				exit(-1);
			}
			int ret = CRYPT_EAL_MdInit(ctx);
			if(ret != CRYPT_SUCCESS){
				printf("error CRYPT_EAL_MdInit %08X\n",ret);
				PrintLastError();
				exit(-1);
			}
			
			////////////////////////////
			//开始实际执行
			for(int testnum=0;testnum<SIZE_NUM;testnum++){
				cipher_message(algs_name[i].name,lengths_list[testnum],TEST_TIME);
				Speed_Time_Test(TM_START);
				
				count = MD_loop(ctx,algs_name[i].buf,lengths_list[testnum]);
				d = Speed_Time_Test(TM_STOP);
                print_result(i, testnum, count, d);
			}
		}
		////////////////////////
		//非对称每个算法都要特殊处理 比较麻烦
		if(algs_name[i].type == ASY_TYPE){
			for(int j=0;j<SIZE_NUM_ASY;j++){
				breaksig = 0;
				int sizebits = lengths_list_asy[j];
				CRYPT_EAL_PkeyCtx *ctx = NULL; 
				///////////////
				//初始化套件
				ctx = CRYPT_EAL_PkeyNewCtx(algs_name[i].alg); 
				if (ctx == NULL) { 
					printf("error CRYPT_EAL_PkeyNewCtx\n");
					exit(-1);
				}
				
				switch(algs_name[i].alg){
					case BSL_CID_RSA:
						//printf("init rsan");
						
						SetRsaPara(&para, e, 3, sizebits);
						SetRsaPubKey(&pubKey, pubE, 600, pubN, 600);  // 600 bytes > 1024 bits
						
						CRYPT_EAL_PkeyGetPub(ctx, &pubKey);
						CRYPT_EAL_PkeySetPara(ctx, &para);
						#define PKCSV15_SIZE ((uint32_t)sizeof(CRYPT_RSA_PkcsV15Para))
						CRYPT_EAL_PkeyCtrl(ctx, CRYPT_CTRL_SET_RSA_EMSA_PKCSV15, &pkcsv15, PKCSV15_SIZE);
						int ret = CRYPT_EAL_PkeyGen(ctx);
						if (ret != CRYPT_SUCCESS) {
							printf("%s not support %d bits\n",algs_name[i].name,sizebits);
							breaksig = 1;
						}
						memset_s(algs_name[i].buf, 32, 'A', 32);
						break;
					case BSL_CID_SM2:
						// 设置用户Id 
					    ret = CRYPT_EAL_PkeyCtrl(ctx, CRYPT_CTRL_SET_SM2_USER_ID, userId, sizeof(userId)); 
					    if (ret != CRYPT_SUCCESS) { 
					        printf("error code is %x\n", ret); 
					        PrintLastError(); 
					        breaksig = 1;
					    } 
						break;
				}
				
				if(breaksig) continue;
				
				//////////////////
				//生成密钥
				asy_print_message("gen",algs_name[i].name,sizebits,TEST_TIME);
				Speed_Time_Test(TM_START);
				count = Gen_loop(ctx,algs_name[i].buf,sizebits/8);
				d = Speed_Time_Test(TM_STOP);
				printf("%ld %u bits %s gen ops in %.2fs\n",
						   count, sizebits, algs_name[i].name ,d);
				asyresults[i][j][0] = (double)count / d;	   
				
				switch(algs_name[i].alg){
					case BSL_CID_RSA:
						///////////////
						//
						mdId = CRYPT_MD_SHA256;
						#define PKCSV15_SIZE ((uint32_t)sizeof(CRYPT_RSA_PkcsV15Para))
						CRYPT_RSA_PkcsV15Para pkcsv15 = {mdId};
						CRYPT_EAL_PkeyCtrl(ctx, CRYPT_CTRL_SET_RSA_EMSA_PKCSV15, &pkcsv15, PKCSV15_SIZE);
						
						//////////////////
						//签名
						asy_print_message("sign",algs_name[i].name,sizebits,TEST_TIME);
						Speed_Time_Test(TM_START);
						count = Sign_loop(ctx,algs_name[i].buf,sizebits/8,CRYPT_MD_SM3,&signLen);
						d = Speed_Time_Test(TM_STOP);
						printf("%ld %u bits %s sign ops in %.2fs\n",
								   count, sizebits,algs_name[i].name, d);
						asyresults[i][j][1] = (double)count / d;	

						CRYPT_EAL_PkeyCtrl(ctx, CRYPT_CTRL_SET_RSA_EMSA_PKCSV15, &pkcsv15, PKCSV15_SIZE);

						//////////////////
						//验签
						asy_print_message("verify",algs_name[i].name,sizebits,TEST_TIME);
						Speed_Time_Test(TM_START);
						count = Verify_loop(ctx,algs_name[i].buf,sizebits/8,CRYPT_MD_SM3,signLen);
						d = Speed_Time_Test(TM_STOP);
						printf("%ld %u bits %s verify ops in %.2fs\n",
								   count, sizebits,algs_name[i].name, d);
						asyresults[i][j][2] = (double)count / d;	
					break;
					case BSL_CID_SM2:
						//////////////////
						//签名
						asy_print_message("sign",algs_name[i].name,sizebits,TEST_TIME);
						Speed_Time_Test(TM_START);
						count = Sign_loop(ctx,algs_name[i].buf,sizebits/8,CRYPT_MD_SM3,&signLen);
						d = Speed_Time_Test(TM_STOP);
						printf("%ld %u bits %s sign ops in %.2fs\n",
								   count, sizebits,algs_name[i].name, d);
						asyresults[i][j][1] = (double)count / d;	
						//////////////////
						//验签
						asy_print_message("verify",algs_name[i].name,sizebits,TEST_TIME);
						Speed_Time_Test(TM_START);
						count = Verify_loop(ctx,algs_name[i].buf,sizebits/8,CRYPT_MD_SM3,signLen);
						d = Speed_Time_Test(TM_STOP);
						printf("%ld %u bits %s verify ops in %.2fs\n",
								   count, sizebits,algs_name[i].name, d);
						asyresults[i][j][2] = (double)count / d;	
					break;
				}
				switch(algs_name[i].alg){
					case BSL_CID_RSA:
						continue;
				}

				//////////////////
				//非对称加密
				asy_print_message("encrypt",algs_name[i].name,sizebits,TEST_TIME);
				Speed_Time_Test(TM_START);
				count = Encrypt_loop(ctx,algs_name[i].buf,sizebits/8,&signLen);
				d = Speed_Time_Test(TM_STOP);
				printf("%ld %u bits %s sign ops in %.2fs\n",
						   count, sizebits,algs_name[i].name, d);
				//使用32字节
				asyresults[i][j][3] = (double)count / d * 32;	


				//////////////////
				//非对称加密
				asy_print_message("decrypt",algs_name[i].name,sizebits,TEST_TIME);
				Speed_Time_Test(TM_START);
				count = Decrypt_loop(ctx,algs_name[i].buf,sizebits/8,signLen);
				d = Speed_Time_Test(TM_STOP);
				printf("%ld %u bits %s sign ops in %.2fs\n",
						   count, sizebits,algs_name[i].name, d);
				asyresults[i][j][4] = (double)count / d * 32;	

				switch(algs_name[i].alg){
				case BSL_CID_SM2:
					j = SIZE_NUM_ASY;
					break;
				}
			}
	
		}
	}
	
	
	////////////////////////
	//输出结果
	print_crypt_header();
	for(int i=0;i<algslen;i++){
		if(algs_name[i].istest == 0){
			continue;
		}
		if(algs_name[i].type == CRYPT_TYPE || algs_name[i].type == MAC_TYPE){
			const char *alg_name = algs_name[i].name;
			printf("%-13s", alg_name);
			
			for (int testnum = 0; testnum < SIZE_NUM; testnum++) {
				if (results[i][testnum] > 10000)
					printf(" %11.2fk", results[i][testnum] / 1e3);
				else
					printf(" %11.2f ", results[i][testnum]);
			}
			printf("\n");
		}
	}
	
	printf("\n\n\n");
	//////////////////
	//输出非对称
	printf("%8s         bits    gen          sign      verify    encrypt    decrypt\n", " ");
	for(int i=0;i<algslen;i++){
		if(algs_name[i].istest == 0){
			continue;
		}
		if(algs_name[i].type == ASY_TYPE){
			for(int j=0;j<SIZE_NUM_ASY;j++){
				int sizebits = lengths_list_asy[j];
				bool endprint = 0;
				const char *alg_name = algs_name[i].name;
				switch(algs_name[i].alg){
					case BSL_CID_RSA:
						printf("%8s %7d bits %8.2f/s %8.2f/s %8.2f/s\n",
					  	 alg_name,sizebits, asyresults[i][j][0], asyresults[i][j][1],asyresults[i][j][2]);
						break;
					case BSL_CID_SM2:
						printf("%8s %7d bits %8.2f/s %8.2f/s %8.2f/s %8.2fk  %8.2fk\n",
					   alg_name,sizebits, asyresults[i][j][0], asyresults[i][j][1],asyresults[i][j][2]
					   ,asyresults[i][j][3]/1e3,asyresults[i][j][4]/1e3);
						endprint = 1;
						break;
				}
				if(endprint)
					break;
			}
		}
	}
	
}


void SetRsaPubKey(CRYPT_EAL_PkeyPub *pubKey, uint8_t *n, uint32_t nLen, uint8_t *e, uint32_t eLen)
{
    pubKey->id = CRYPT_PKEY_RSA;
    pubKey->key.rsaPub.n = n;
    pubKey->key.rsaPub.nLen = nLen;
    pubKey->key.rsaPub.e = e;
    pubKey->key.rsaPub.eLen = eLen;
}

void SetRsaPara(CRYPT_EAL_PkeyPara *para, uint8_t *e, uint32_t eLen, uint32_t bits)
{
    para->id = CRYPT_PKEY_RSA;
    para->para.rsaPara.e = e;
    para->para.rsaPara.eLen = eLen;
    para->para.rsaPara.bits = bits;
}